#include <iostream>
#include <string>
using namespace std;

/***********************friend 关键字***********************
    在C++中，friend关键字用于声明一个函数或类为另一个类的友元。
        友元可以访问类的私有和保护成员，但不能访问类的公有成员。
        友元函数可以在类的对象之间共享数据，而友元类则可以继承类的所有成员。

    友元的三种:
        全局函数为友元函数
        类成员函数为友元函数
        类为友元类(友元对象)

*/

class B; // 前向声明
class A;

class C
{
    public:
        //类的成员函数作为友元函数
        void get_members_member(A &a);
        C()
        {
            cout << "C构造函数" << endl;
        }
        ~C()
        {
            cout << "C析构函数" << endl;
        }
};

class A
{
    private:
        string name_;
        int age_;
    public:
        A(const string name,const int age) : name_(name), age_(age) {cout << "A构造函数 初始化参数" << endl;};
        virtual ~A()
        {
            cout << "A析构函数 " << endl;
        }
        void func()
        {
            std::cout << "A's func()" << std::endl;
        }

        
        friend void get_members_global(A & a);  // 友元全局函数，可以访问A的私有成员变量和所有的公有成员
        friend void C::get_members_member(A &a); // C的成员函数做友元函数，可以访问.....
        friend class B; // 声明B为A的友元类，B中成员函数可以访问A中所有的成员
        
};

class B
{
    private:
        string name_;
        int age_;
    public:
        B(const string name,const int age) : name_(name), age_(age) {cout << "B构造函数 初始化参数" << endl;};
        virtual ~B()
        {
            cout << "B析构函数 " << endl;
        }
        void func()
        {
            std::cout << "B's func()" << std::endl;
        };
        // 友元类
        void get_members_class(A & a)
        {
            cout << a.name_ << " is " << a.age_ << " years old " << endl;
        a.func();
        };

};




// 全局函数作为友元函数
void get_members_global(A & a)
{
    cout << a.name_ << " is " << a.age_ << " years old " << endl;
    a.func();
}

// 类的成员函数作为友元函数
void C::get_members_member(A &a)
{
    cout << a.name_ << " is " << a.age_ << " years old " << endl;
    a.func();
}

int main()
{
    A a("Hubery",45);
    B b("Tom",24);
    C c;

    cout << "***************************全局函数作为友元函数***************************" << endl;

    get_members_global(a);

    cout << "***************************类的成员函数作为友元函数***************************" << endl;

    c.get_members_member(a);


    cout << "***************************友元类***************************" << endl;
    b.get_members_class(a);

    return 0;
}
